/************************************
*  Copyright (C) 2010 Julien MOTTIN.
*  Contact: julien.mottin@gueydan.eu
*
*  This file is part of Gueydan.
*
*  Gueydan is free software: you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation, either version 3 of the License, or
*  (at your option) any later version.
*
*  Gueydan is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with Gueydan.  If not, see <http://www.gnu.org/licenses/>.
*
*************************************/
// Local
#include "mash_step.h"
#include "xmldico.h"

// QtCore
#include <QtGlobal>

// QtXml
#include <QDomNode>
#include <QDomElement>
#include <QDomDocument>
#include <QDomNodeList>
#include <QDomText>

MashStep::MashStep(const QString &iName, int iVersion, MashStepType iType, const Temperature &iStepTemp, const Duration &iStepDuration, const Volume &iInfuseAmount)
:BeerXMLObject(iName,iVersion)
,_Type(iType)
,_StepTemp(iStepTemp)
,_StepTime(iStepDuration)
,_InfuseAmount(iInfuseAmount)
,_RampTime(0.0)
,_EndTemp(0.0)
{
    if (_Type!=MSTInfusion)
        _InfuseAmount = 0.0;
}

MashStep::MashStep()
:BeerXMLObject()
,_Type(MSTTemperature)
,_StepTemp(0.0)
,_StepTime(0.0)
,_InfuseAmount(0.0)
,_RampTime(0.0)
,_EndTemp(0.0)
{
}

MashStep::~MashStep()
{
}

bool MashStep::operator==(const MashStep &iOther) const
{
    return ((*this).BeerXMLObject::operator==(iOther) &&
            _Type == iOther._Type &&
            _StepTemp == iOther._StepTemp &&
            _StepTime == iOther._StepTime &&
            _InfuseAmount == iOther._InfuseAmount &&
            _RampTime == iOther._RampTime &&
            _EndTemp == iOther._EndTemp);
}

bool MashStep::operator!=(const MashStep &iOther) const
{
    return (!((*this)==iOther));
}

int MashStep::CreateFromXMLNode(const QDomNode &iNode)
{
    int oRC = 1;
    if (!iNode.isNull())
    {
        QDomElement MashStepElement;

        // Case Document : check if doc has only one Hop element
        if (iNode.isDocument())
        {
            QDomDocument MashStepDoc = iNode.toDocument();
            QDomNodeList MashStepList = MashStepDoc.elementsByTagName(MASHSTEP);
            if (MashStepList.length()==1)
                MashStepElement = MashStepList.item(0).toElement();
        }
        // Default : cast to element
        else
            MashStepElement = iNode.toElement();

        // Check element consistency
        if (!MashStepElement.isNull() && MASHSTEP==MashStepElement.tagName())
        {
            // Check existence of mandatory elements
            bool MashStepName = false;
            bool MashStepVersion = false;
            bool MashStepType = false;
            bool MashStepTemp = false;
            bool MashStepTime = false;
            QDomNode node = MashStepElement.firstChild();
            while (!node.isNull())
            {
                if (node.isElement())
                {
                    QDomElement elem = node.toElement();
                    QString name = elem.tagName();
                    QString text = elem.text();
                    if (name==MASHSTEP_NAME)
                    {
                        _Name = text;
                        MashStepName = true;
                    }
                    else if (name==MASHSTEP_VERSION)
                    {
                        bool ok = false;
                        int v = text.toInt(&ok);
                        if (ok)
                        {
                            _Version = v;
                            MashStepVersion = true;
                        }
                    }
                    else if (name==MASHSTEP_TYPE)
                    {
                        MashStepType = true;
                        QString type = text.toLower();
                        if (type==MASHSTEP_TYPE_INFUSION.toLower())
                            _Type = MSTInfusion;
                        else if (type==MASHSTEP_TYPE_TEMP.toLower())
                            _Type = MSTTemperature;
                        else if (type==MASHSTEP_TYPE_DECOCTION.toLower())
                            _Type = MSTDecoction;
                        else
                            MashStepType = false;
                    }
                    else if (name==MASHSTEP_INFUSEAMOUNT)
                    {
                        bool ok = false;
                        _InfuseAmount.FromString(text,&ok);
                    }
                    else if (name==MASHSTEP_TEMP)
                    {
                        bool ok = false;
                        _StepTemp.FromString(text,&ok);
                        if (ok)
                            MashStepTemp = true;
                    }
                    else if (name==MASHSTEP_TIME)
                    {
                        bool ok = false;
                        _StepTime.FromString(text,&ok);
                        if (ok)
                            MashStepTime = true;
                    }
                    else if (name==MASHSTEP_RAMPTIME)
                    {
                        bool ok = false;
                        _RampTime.FromString(text,&ok);
                    }
                    else if (name==MASHSTEP_ENDTEMP)
                    {
                        bool ok = false;
                        _EndTemp.FromString(text,&ok);
                    }
                }

                // Iterate
                node = node.nextSibling();
            }

            // Check & update output
            if (MashStepName && MashStepVersion && MashStepType && MashStepTemp && MashStepTime)
            {
                oRC = 0;
            }
        }
    }
    return oRC;
}


int MashStep::ToXMLNode(QDomNode &iParentNode) const
{
    int oRC = 1;

    // First, create valid element node
    QDomDocument doc = iParentNode.ownerDocument();
    QDomElement MashStepNode = doc.createElement(MASHSTEP);
    if (!MashStepNode.isNull())
    {
        if (!_Name.isEmpty() && _Version>0)
        {
            QDomElement node;
            QDomText textNode;
            QString str;

            // Name
            node = doc.createElement(MASHSTEP_NAME);
            Q_ASSERT(!node.isNull());
            textNode = doc.createTextNode(_Name);
            Q_ASSERT(!textNode.isNull());
            node.appendChild(textNode);
            MashStepNode.appendChild(node);

            // Version
            node = doc.createElement(MASHSTEP_VERSION);
            Q_ASSERT(!node.isNull());
            textNode = doc.createTextNode(QString::number(_Version));
            Q_ASSERT(!textNode.isNull());
            node.appendChild(textNode);
            MashStepNode.appendChild(node);

            // Type
            switch (_Type)
            {
            case MSTInfusion:
                str = MASHSTEP_TYPE_INFUSION;
                break;
            case MSTTemperature:
                str = MASHSTEP_TYPE_TEMP;
                break;
            case MSTDecoction:
                str = MASHSTEP_TYPE_DECOCTION;
            }
            node = doc.createElement(MASHSTEP_TYPE);
            Q_ASSERT(!node.isNull());
            textNode = doc.createTextNode(str);
            Q_ASSERT(!textNode.isNull());
            node.appendChild(textNode);
            MashStepNode.appendChild(node);

            // InfuseAmount
            if (_InfuseAmount>0)
            {
                node = doc.createElement(MASHSTEP_INFUSEAMOUNT);
                Q_ASSERT(!node.isNull());
                textNode = doc.createTextNode(QString::number(_InfuseAmount.Value(Liter)));
                Q_ASSERT(!textNode.isNull());
                node.appendChild(textNode);
                MashStepNode.appendChild(node);
            }

            // Step Temp
            node = doc.createElement(MASHSTEP_TEMP);
            Q_ASSERT(!node.isNull());
            textNode = doc.createTextNode(QString::number(_StepTemp.Value(Celsius)));
            Q_ASSERT(!textNode.isNull());
            node.appendChild(textNode);
            MashStepNode.appendChild(node);

            // Step Time
            node = doc.createElement(MASHSTEP_TIME);
            Q_ASSERT(!node.isNull());
            textNode = doc.createTextNode(QString::number(_StepTime.Value(Minute)));
            Q_ASSERT(!textNode.isNull());
            node.appendChild(textNode);
            MashStepNode.appendChild(node);

            // Ramp time
            if (_RampTime>0)
            {
                node = doc.createElement(MASHSTEP_RAMPTIME);
                Q_ASSERT(!node.isNull());
                textNode = doc.createTextNode(QString::number(_RampTime.Value(Minute)));
                Q_ASSERT(!textNode.isNull());
                node.appendChild(textNode);
                MashStepNode.appendChild(node);
            }

            // End temp
            if (_EndTemp>0)
            {
                node = doc.createElement(MASHSTEP_RAMPTIME);
                Q_ASSERT(!node.isNull());
                textNode = doc.createTextNode(QString::number(_EndTemp.Value(Celsius)));
                Q_ASSERT(!textNode.isNull());
                node.appendChild(textNode);
                MashStepNode.appendChild(node);
            }

            // Update output
            QDomNode zeNode = iParentNode.appendChild(MashStepNode);
            if (!zeNode.isNull())
                oRC = 0;
        }
    }

    return oRC;
}
